#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2023/2/1 10:13
# @Author : zxiaosi
# @desc : 路由日志记录器
import time
from typing import Callable
from urllib.parse import parse_qsl

from fastapi.encoders import jsonable_encoder
from fastapi.routing import APIRoute
from fastapi.requests import Request
from fastapi.responses import Response
from common.custom_log import my_logger


# 详见: https://fastapi.tiangolo.com/advanced/custom-request-and-route/#custom-apiroute-class-in-a-router


class LogRoute(APIRoute):
    def get_route_handler(self) -> Callable:
        original_route_handler = super().get_route_handler()

        async def custom_route_handler(request: Request) -> Response:
            before = time.time()
            response: Response = await original_route_handler(request)
            duration = time.time() - before
            response.headers["X-Response-Time"] = str(duration)
            request_params = await get_request_params(request)
            request_params['path'] = self.path
            my_logger.info(f"访问记录: {jsonable_encoder(request_params)}.")
            return response

        return custom_route_handler


async def get_request_params(request: Request) -> dict:
    """ 获取请求参数 """
    params: dict = {}  # 存储结果
    path_params = request.get("path_params")  # 路径参数
    if path_params:
        params.update(path_params)

    query_string = request.get("query_string")
    if query_string:
        query_params = parse_qsl(str(query_string, "utf-8"))  # 查询参数
        params.update(query_params)

    methods = ["POST", "PUT", "PATCH"]
    content_type = request.headers.get("content-type")
    # if content_type is not None and request.method in methods and "application/json" in content_type:
    #     body_params = await request.json()  # 请求体参数
    #     if body_params is not None:
    #         params.update(body_params)
    params['host'] = request.headers.get('host')
    params['method'] = request.method
    params['content_type'] = content_type
    return params
